package com.jie.common.util;

import com.jie.common.message.constant.MessageConstant;

/**
 * 处理字节数组的工具类
 * @author XieZhiJie
 * @date 2022/04/21 14:27
 */
public class BytesUtil {

    /**
     * 将一个int数字转为byte数组, byte数组长度为: MessageConstant.MESSAGE_HEAD_LENGTH
     * @param value int数组
     * @return      返回转化后的数组
     */
    public static byte[] transformIntToBytes(int value) {
        return transformIntToBytes(value, MessageConstant.MESSAGE_HEAD_LENGTH);
    }

    /**
     * 将一个int数字转为byte数组
     * 注意: 不论bytesLength多长, 最大只能为4, 因为int是4个字节
     * @param value       int数字
     * @param bytesLength 要转化的字节数组长度
     * @return            返回转化后的字节数组
     */
    public static byte[] transformIntToBytes(int value, int bytesLength) {
        bytesLength = Math.min(4, bytesLength);
        byte[] result = new byte[bytesLength];
        while (value != 0 && bytesLength > 0) {
            result[--bytesLength] = (byte) value;
            value >>= 8;
        }
        return result;
    }

    /**
     * 将一个bytes数组转为int数字, 默认转换的bytes数组长度为: MessageConstant.MESSAGE_HEAD_LENGTH
     * @param bytes bytes数组
     * @return      返回转换后的int数字
     */
    public static int transformBytesToInt(byte[] bytes) {
        return transformBytesToInt(bytes, MessageConstant.MESSAGE_HEAD_LENGTH);
    }

    /**
     * 将一个bytes数组转为int数字
     * 注意: 不论要转换的length多长, 都不超过4
     * @param bytes  bytes数组
     * @param length 需要将bytes数组前length个字节转为int
     * @return       返回转化后的int数字
     */
    public static int transformBytesToInt(byte[] bytes, int length) {
        length = Math.min(4, length);
        int value = 0;
        for (int i = 0; i < length; i++) {
            // 因为java是有符号的, 因此需要注意
            value <<= 8;
            value |= (0xff & bytes[i]);
        }
        return value;
    }

    /**
     * 将两个字节数组组合在一起, 可以拆分
     * MessageConstant.MESSAGE_HEAD_LENGTH字节的字节数组1长度 + 字节数组1 + 字节数组2
     * @param bytes1 字节数组1, 需要记录其长度
     * @param bytes2 字节数组2
     * @return       返回组合后的字节数组
     */
    public static byte[] packageTwoBytesWithLengthBytes(byte[] bytes1, byte[] bytes2) {
        byte[] bytes1LengthBytes = transformIntToBytes(bytes1.length);
        byte[] result = new byte[bytes1LengthBytes.length + bytes1.length + bytes2.length];
        System.arraycopy(bytes1LengthBytes, 0, result, 0, bytes1LengthBytes.length);
        System.arraycopy(bytes1, 0, result, bytes1LengthBytes.length, bytes1.length);
        System.arraycopy(bytes2, 0, result, bytes1LengthBytes.length + bytes1.length, bytes2.length);
        return result;
    }

    /**
     * 将一个字节数组拆分为两个字节数组
     * 根据前MessageConstant.MESSAGE_HEAD_LENGTH个字节得知字节数组1多长, 以此拆分出两个字节数组
     * @param bytes MessageConstant.MESSAGE_HEAD_LENGTH字节第一个字节数组的长度 + 字节数组1 + 字节数组2
     * @return      返回拆分后的两个字节数组
     */
    public static byte[][] splitBytesToTwoBytes(byte[] bytes) {
        int bytes1Length = transformBytesToInt(bytes);
        byte[] bytes1 = new byte[bytes1Length];
        byte[] bytes2 = new byte[bytes.length - MessageConstant.MESSAGE_HEAD_LENGTH - bytes1.length];
        System.arraycopy(bytes, MessageConstant.MESSAGE_HEAD_LENGTH, bytes1, 0, bytes1.length);
        System.arraycopy(bytes, MessageConstant.MESSAGE_HEAD_LENGTH + bytes1.length, bytes2, 0, bytes2.length);
        return new byte[][] {bytes1, bytes2};
    }

    /**
     * 将多个字节数组合并在一起, 无法拆分
     * @param bytesArray 多个字节数组
     * @return           返回合并后的字节数组
     */
    public static byte[] packetBytes(byte[] ...bytesArray) {
        int resultsLength = 0;
        for (byte[] bytes : bytesArray) {
            resultsLength += bytes.length;
        }
        byte[] results = new byte[resultsLength];
        int offset = 0;
        for (byte[] bytes : bytesArray) {
            System.arraycopy(bytes, 0, results, offset, bytes.length);
            offset += bytes.length;
        }
        return results;
    }

    /**
     * 对比bytes数组与多个bytes数组相连是否相同
     * @param bytes      bytes数组
     * @param bytesArray 多个bytes数组
     * @return           返回是否相同
     */
    public static boolean compareBytesAndBytesArray(byte[] bytes, byte[] ...bytesArray) {
        int offset = 0;
        for (byte[] otherBytes : bytesArray) {
            for (int i = 0; i < otherBytes.length && offset < bytes.length; i++, offset++) {
                if (otherBytes[i] != bytes[offset]) {
                    return false;
                }
            }
        }
        return offset == bytes.length;
    }

}
